package test07.instrospction;

import test00.Student;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;


/**
 * 基于内省操作 - 内省是反射的扩展 - 针对 JavaBean 这个特殊的类进行相关操作
 *
 *
 * @Author lzp
 * @Date 2024-03-27
 */
public class BeanUtil {

    /**
     *
     * 给任意对象任意属性设置值 - 实现一
     *
     * @param bean  任意对象
     * @param propertyName 任意属性
     * @param value 数据
     */

    public static void setProperty01(Object bean,
                                     String propertyName,Object value) throws Exception {

        //获取 JavaBean 对象的 BeanInfo 对象 清除父类
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(),Object.class);

        //获取属性列表
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        //循环遍历所有属性 匹配设置的属性值 ，找到它的 setter方法 - 调用
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

                if (propertyDescriptor.getName().equals(propertyName)){
                    propertyDescriptor.getWriteMethod().invoke(bean,value);
                    break;
                }
        }

    }

    /**
     *
     * 给任意对象任意属性设置值 - 实现二
     *
     * @param bean  任意对象
     * @param propertyName 任意属性
     * @param value 数据
     * */
    public static void setProperty02(Object bean,
                                     String propertyName,Object value) throws Exception {

        //创建属性描述器对象
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName,bean.getClass());

        propertyDescriptor.getWriteMethod().invoke(bean,value);


    }

    /**
     * 获取任意对象任意属性值 - 实现一
     *
     * @param bean         任意对象
     * @param propertyName 任意属性
     * @return 属性值
     */
    public static Object getProperty01(Object bean,String propertyName) throws Exception {
        //获取 JavaBean 对象的 BeanInfo 对象 清除父类
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(),Object.class);

        //获取属性列表
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

        //循环遍历所有属性 匹配设置的属性值 ，找到它的 getter方法 - 调用
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            if (propertyDescriptor.getName().equals(propertyName)){
               return propertyDescriptor.getReadMethod().invoke(bean);
            }
        }
        return null;
    }

    /**
     * 获取任意对象任意属性值 - 实现二
     *
     * @param bean         任意对象
     * @param propertyName 任意属性
     * @return 属性值
     */
    public static Object getProperty02(Object bean,String propertyName) throws Exception {
        //创建属性描述器对象
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName,bean.getClass());

        return propertyDescriptor.getReadMethod().invoke(bean);
    }

    /**
     *
     * 复制对象属性
     *
     * @param source 源对象
     * @param target 目标对象
     */
    public static void copyProperties(Object source,Object target) throws Exception {

        //获取源对象的 BeanInfo 对象
        BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass(),Object.class);

        //获取源对象的属性描述器列表 - 遍历循环 - 获取属性值以及名称
        //根据属性名创建属性描述器对象 - 获取 setter 方法 调用
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            //获取源对象属性名称
            String propertyname = propertyDescriptor.getName();
            //获取源对象属性值
            Object value = propertyDescriptor.getReadMethod().invoke(source);
            //根据源对象属性名称 创建目标对象的属性描述器对象
            PropertyDescriptor tar = new PropertyDescriptor(propertyname,target.getClass());
            //获取目标对象的 setter 方法，调用
            tar.getWriteMethod().invoke(target,value);
        }



    }

    public static void main(String[] args) throws Exception {
        Student stu = new Student();

        // 给 Bean 对象设置属性
        BeanUtil.setProperty01(stu,"name","张三");
        BeanUtil.setProperty02(stu,"age",18);

        // 获取 Bean 对象的属性值
        Object name = BeanUtil.getProperty01(stu, "name");
        Object age = BeanUtil.getProperty02(stu, "age");

        System.out.println(name);
        System.out.println(age);

        Student stu1 = new Student("张三", 18, 99D);
        Student stu2 = new Student();

        System.out.println(stu2);
        BeanUtil.copyProperties(stu1,stu2);
        System.out.println(stu2);



    }

}
